/* eslint-disable @typescript-eslint/no-var-requires */
const IO = require('socket.io');
import * as chatUtil from '../../model/service/chat/index';
import { updateUserInfoService } from '../../model/service/account/updateInfo'
import { getUserInfo } from '../../model/service/account/userInfo';

function emitAsync(socket: import('socket.io').Socket, emitName: string, data: string, callback: (userId: string) => void): Promise<void> {
  return new Promise((resolve, reject) => {
      if (!socket || !socket.emit) {
          reject('pls input socket');
      }

      chatUtil.getOfflineMsgList('d896qvpzp5s00');
      socket.emit(emitName, data, (userId: string) => {
          let response;
          if (typeof callback === 'function') {
              response = callback(userId);
          }
          resolve(response);
      });
  });
}

export default function createSocket(server: import('http').Server) {
  // 创建socket实例
  const io = IO(server, { 
    pingInterval: 1000,
    pingTimeout: 5000,
    cookie: false,
    origins: "*",
  });  

  //每个客户端socket连接时都会触发 connection 事件
  io.on("connection", async (clientSocket: import('socket.io').Socket) => { 
    const socket_id = clientSocket.id
    let userId: string;
    console.log('connection socketId=>', socket_id, 'time=>', new Date().toLocaleString());
    // 必须先把socketID先进行保存
    await emitAsync(clientSocket, 'initSocket', clientSocket.id, (uid: string) => {
      userId = uid;
      updateUserInfoService({
        uid: userId,
        socketId: socket_id
      })
      console.log('initSocket=>  userId=> ', userId, 'time=>', new Date().toLocaleString());
    })

    // 初始化成功并获取 获取好友列表及消息
    clientSocket.on('initSocketSuccess', async (userId: string, fn) => {
        console.log('initSocketSuccess=>', 'time=>', new Date().toLocaleString());
        try {
            const [allMessage, friendList] = await Promise.all([
              chatUtil.getOfflineMsgList(userId),
              chatUtil.getFriendList(userId),
            ]);
            // 先不格式化
            // allMessage.forEach(item=>{
            //     item.attachments = JSON.parse(item.attachments)
            // })
            // 返回好友列表及离线信息
            fn(allMessage, friendList)
            // 返回之后从数据库里面删除这些离线信息
            chatUtil.deleteOfflineMsg(userId)
        } catch (err) {
            console.log(err);
        }
    })

    clientSocket.on('sendPrivateMsg', async (data, fn) => {
        // 数据消息一般类型
        // {  
        //     from_user:22256, 自己的id
        //     to_user:1234654, 对方id
        //     avatar, // 自己的头像
        //     name,
        //     message:'123456',
        //     attachments:[]数组    {fileUrl:'',type:'image,video,voice,file',name:''}
        // }
        try {
            if (!data) return;
            await Promise.all([
                chatUtil.saveUserMsgList(data),
                getUserInfo({uid: data.toUser}).then(arr => {
                    const userSocketId = arr[0].socketId;
                    if (io.sockets?.sockets?.get(userSocketId)) {
                      getUserInfo({ uid: data.fromUser }).then((res) => {
                        const result = res[0];
                        data = {
                          ...data,
                          profile: result.profile,
                          username: result.username,
                        },
                        console.log('推送成功', data);
                        io.to(userSocketId).emit('getPrivateMsg', data);
                      })
                    } else {
                        console.log('对方不在线 消息存入离线消息库');
                        chatUtil.saveOfflineMsgList(data)
                    }

                }),
            ]);
            console.log('sendPrivateMsg data=>', data, 'time=>', new Date().toLocaleString());
            fn({success: true, message: '发送成功',data:data});
        } catch (error) {
            console.log('error', error.message);
            io.to(socket_id).emit('error', {
                code: 500,
                message: error.message
            });
        }
        // console.log(fn);
    })

    clientSocket.on("connect_error", (err: IAnyObject) => {
      console.log(`connect_error due to ${err.message}`);
    });
   })
}